import _ from 'lodash';
import axios from 'axios';
import isFunction from 'lodash/isFunction';

// CORS settings
axios.defaults.withCredentials = true;

export const callApi = (endpoint, params, config = {}, next) => {
  if (config.needCancel) {
    const source = axios.CancelToken.source();
    next({
      type: 'REMOVE_CANCEL_TOKEN',
      payload: {
        key: endpoint,
      },
    });
    next({
      type: 'ADD_CANCEL_TOKEN',
      payload: {
        key: endpoint,
        source,
      },
    });
    config.cancelToken = source.token;
  }
  return axios.post(endpoint, params || {}, config).then((response) => {
    response = _.get(response, 'data', {});
    const { code } = response;
    const msg = _.get(response, 'message') || _.get(response, 'msg');

    // 104 - 退出成功，重新登录
    // 105 - 登录超时，重新登录
    if (code === 105 || code === 104 || code === 111) {
      window.location.href = '/signin';
    } else if (code === 302) {
      const rurl = `${window.location.origin}/highspeed-perception`;
      const location = `${process.env.REACT_APP_HAIRUO_API_ROOT + _.get(response, 'data.location')}&rurl=${rurl}`;
      window.location.href = location;
    }

    if (code !== 0) {
      const error = new Error(msg);
      error.data = response;
      throw error;
    }

    return response;
  });
  // .finally(() => {
  //     if (config.needCancel) {
  //         next({
  //             type: 'REMOVE_CANCEL_TOKEN',
  //             payload: {
  //                 key: endpoint
  //             }
  //         });
  //     }
  // });
};

export const CALL_API = 'Call API';

const APP_DO_NOTHING = 'APP_DO_NOTHING';
const APP_IGNORE = 'APP_IGNORE';

export default function api(store){
  // next指的是聚合函数(第一次的时候是dispatch函数)，聚合函数主要看compose(相当于compose的那个a)
  // action：dispatch的参数，有可能是函数、异步函数
  return next => action => {
    const callAPI = action[CALL_API];

    if (typeof callAPI === 'undefined') {
      return next(action);
    }

    let { endpoint, normalize, types, config = {} } = callAPI;
    const { params, getKeys } = callAPI;
    // 什么时候用
    // if (typeof endpoint === 'function') {
    //   endpoint = endpoint(store.getState());
    // }

    if (normalize === null || normalize === undefined) {
      normalize = data => _.get(data, 'data'); // 提供一个方法
    }

    if (!isFunction(normalize)) {
      throw new Error('Normalize should be a function');
    }

    if (typeof endpoint !== 'string') {
      throw new Error('Specify a string endpoint URL.');
    }

    if (types === null || types === undefined) {
      types = [APP_DO_NOTHING, APP_DO_NOTHING, APP_DO_NOTHING]; // 干吗用
    }

    if (!Array.isArray(types) || types.length !== 3) {
      throw new Error('Expected an array of three action types.');
    }

    const [requestType, successType, failureType] = types.map(item => item || APP_IGNORE);

    const actionWith = (data) => {
      const finalAction = { params, ...action, ...data };
      delete finalAction[CALL_API];
      // req里多次修改entities，当接口返回后suc里的entities会覆盖【暂时解决方案 后续需要增加同请求abort机制】
      if (data.type === successType && !data.entities && action.entities) {
        delete finalAction.entities;
      }
  
      // if (isFunction(getKeys)) {
      //   finalAction.keys = getKeys(finalAction);
      // }
      return finalAction;
    };

    next(actionWith({ type: requestType }));

    return callApi(endpoint, params, config, next).then(
      resp => next(actionWith({
        ...normalize(resp),
        type: successType,
        __response: resp,
      })),
      error => next(actionWith({
        type: failureType,
        error: error.message || 'Something bad happened',
        data: error.data,
        __response: error.data,
      })),
    );
  };
}